home *** CD-ROM | disk | FTP | other *** search
/ AGA Toolkit '97 / The AGA Toolkit '97.iso / c / du.c < prev    next >
C/C++ Source or Header  |  1996-09-07  |  8KB  |  289 lines

  1.  
  2. /********************************************************************\
  3. *                                     *
  4. *            Dave's DU version 1.01                       *
  5. *                                     *
  6. * ©1991 by Dave Schreiber.  All rights reserved.  This program may   *
  7. * be freely distributed.  The only charges allowed in relation to    *
  8. * distributing this program is in relation to media, shipping, and   *
  9. * handling costs.                             *
  10. *                                     *
  11. * Version list:                              *
  12. *   1.02 (05/24/91) - Improved CTRL-C handling                       *
  13. *   1.00 (04/29/91) - Original release version                       *
  14. *                                     *
  15. * Compiled with SAS/C V5.10.  To compile, do the following:         *
  16. *   1> lc DU                                 *
  17. *   1> blink with DU.lnk                         *
  18. *                                     *
  19. \********************************************************************/
  20.  
  21.  
  22. #include <exec/types.h>
  23. #include <exec/exec.h>
  24. #include <exec/tasks.h>
  25. #include <dos/dos.h>
  26. #include <dos/dosextens.h>
  27. #include <stdio.h>
  28. #include <signal.h>
  29.  
  30. ULONG *DOSBase;
  31.  
  32. /*Function prototypes*/
  33.  
  34. ULONG __regargs getDirSize(BPTR lock,char *dirName);
  35. void interpretArgs(int argc,char *argv[],WORD *countDirs,WORD *countFiles,
  36.             char *dirName);
  37. void printSize(char *dirName,ULONG size);
  38. void printHelp(void);
  39. void ctrlC_Handler(void);
  40.  
  41. /*-------------------*/
  42.  
  43. /*Pragmas*/
  44.  
  45. #pragma syscall AllocMem C6 1002
  46. #pragma syscall FreeMem D2 0902
  47. #pragma syscall FindTask 126 901
  48.  
  49. #pragma libcall DOSBase CurrentDir 7E 101
  50. #pragma libcall DOSBase Examine 66 2102
  51. #pragma libcall DOSBase ExNext 6C 2102
  52. #pragma libcall DOSBase Lock 54 2102
  53. #pragma libcall DOSBase UnLock 5A 101
  54.  
  55. /*-------*/
  56.  
  57. /*Global variables*/
  58.  
  59. WORD countFiles,countDirs;
  60. struct Task *task;
  61. BYTE quitNow=FALSE;
  62.  
  63. /*----------------*/
  64.  
  65. /*Defines*/
  66.  
  67. #define ERROR 0xFFFFFFFF
  68. #define ABS(x) ((x) < 0 ? -(x) : (x))
  69.  
  70. /*-------*/
  71.  
  72. /*Main.  Initializes, find the directory size, and then cleans up*/
  73. main(int argc,char *argv[])
  74. {
  75.    BPTR lock;
  76.    char dirName[256];
  77.    LONG totalSize;
  78.  
  79.       /*Interpret the command line arguments*/
  80.    interpretArgs(argc,argv,&countDirs,&countFiles,dirName);
  81.  
  82.       /*Replace the CTRL-C handler*/
  83.    signal(SIGINT,ctrlC_Handler);
  84.  
  85.       /*Get a lock on the provided directory name*/
  86.    lock=Lock(dirName,SHARED_LOCK);
  87.    if(lock == NULL)  /*Abort if the directory isn't there*/
  88.    {
  89.       fputs("Couldn't access the directory you requested;  aborting.\n",
  90.         stderr);
  91.       exit(200);
  92.    }
  93.  
  94.       /*Get the size of the contents of the directory*/
  95.    totalSize=getDirSize(lock,dirName);
  96.  
  97.       /*Abort if something went wrong, otherwise print the directory size*/
  98.    if(totalSize == ERROR)
  99.       fputs("Error.  Aborting!\n",stderr);
  100.    else
  101.       if(!countDirs && !quitNow)
  102.      printSize(dirName,totalSize);
  103.  
  104.    UnLock(lock);  /*Free the lock on the top directory*/
  105.    exit(0);       /*And exit*/
  106. }
  107.  
  108. /*Get the size of the contents of the specified directory (recursive)*/
  109. ULONG __regargs getDirSize(BPTR lock,char *dirName)
  110. {
  111.    register ULONG totalSize=0;
  112.    register struct FileInfoBlock *fib;
  113.    register BPTR dirLock,oldCurDir;
  114.    register UWORD dirNameLen;
  115.    register ULONG size;
  116.  
  117.    dirNameLen=strlen(dirName);
  118.  
  119.       /*Allocate (longword aligned) FileInfoBlock structure*/
  120.    fib=(struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),
  121.            MEMF_PUBLIC,MEMF_CLEAR);
  122.    if(fib==NULL)
  123.       return(ERROR);
  124.  
  125.       /*Save the current directory, and change to the directory we need*/
  126.       /*to find the size of.*/
  127.    oldCurDir=CurrentDir(lock);
  128.    Examine(lock,fib);
  129.  
  130.       /*For each file/directory, get the size...*/
  131.    while(ExNext(lock,fib) && !quitNow)
  132.    {
  133.       totalSize++;    /*Add 1 (for the directory entry)*/
  134.       if(ABS(fib->fib_EntryType) != 4)  /*If the file isn't a link...*/
  135.       {
  136.      if(fib->fib_EntryType < 0)  /*If the file isn't a directory*/
  137.      {                     /*get the size directly*/
  138.            /*Add the size to the total*/
  139.         totalSize+=fib->fib_NumBlocks;
  140.  
  141.         if(countFiles) /*If the user wants the size of each file*/
  142.         {           /*printed, print the file size*/
  143.            if(dirNameLen!=0 && dirName[dirNameLen-1]!=':')
  144.           strcat(dirName,"/");
  145.            strcat(dirName,fib->fib_FileName);
  146.            printSize(dirName,totalSize);
  147.            dirName[dirNameLen]=NULL;
  148.         }
  149.      }
  150.      else  /*It's a directory*/
  151.      {
  152.            /*Get the lock on the directory*/
  153.         dirLock = Lock(fib->fib_FileName,SHARED_LOCK);
  154.  
  155.         if(dirLock == NULL)  /*Abort if there was a problem getting*/
  156.         {             /*a lock on the directory*/
  157.            CurrentDir(oldCurDir);
  158.            fputs("Couldn't lock directory:",stderr);
  159.            fputs(fib->fib_FileName,stderr);
  160.            fputs("\n",stderr);
  161.            FreeMem(fib,sizeof(struct FileInfoBlock));
  162.            return(ERROR);
  163.         }
  164.            /*Create the full name of the directory we're going to */
  165.            /*descend into*/
  166.         if(dirNameLen!=0 && dirName[dirNameLen-1]!=':')
  167.            strcat(dirName,"/");
  168.         strcat(dirName,fib->fib_FileName);
  169.  
  170.            /*Recursively get the directory size*/
  171.         size=getDirSize(dirLock,dirName)-1;
  172.         UnLock(dirLock);
  173.  
  174.         if(size==ERROR)   /*Abort if there was an error*/
  175.         {
  176.            CurrentDir(oldCurDir);
  177.            FreeMem(fib,sizeof(struct FileInfoBlock));
  178.            return(ERROR);
  179.         }
  180.         else
  181.            totalSize+=size+2;  /*Otherwise, add the size to the total*/
  182.  
  183.            /*Restore the old directory name*/
  184.         dirName[dirNameLen]=NULL;
  185.      }
  186.       }
  187.    }
  188.    CurrentDir(oldCurDir);
  189.  
  190.    if(quitNow)    /*If the user pressed CTRL-C, abort*/
  191.       fputs("*** Break: du\n",stderr);
  192.    else
  193.       if(countDirs)  /*If CTRL-C wasn't pressed, print the size of the*/
  194.      printSize(dirName,totalSize); /*directory (if the user wants it)*/
  195.  
  196.       /*Deallocate the FileInfoBlock*/
  197.    FreeMem(fib,sizeof(struct FileInfoBlock));
  198.       /*Return the total size*/
  199.    return(totalSize);
  200. }
  201.  
  202. /*Interpret the command line arguments*/
  203. void interpretArgs(int argc,char *argv[],WORD *countDirs,WORD *countFiles,
  204.             char *dirName)
  205. {
  206.    int i;
  207.  
  208.    if(argv[1][0]=='?')  /*The user is asking for help*/
  209.    {
  210.       printHelp();
  211.       exit(0);
  212.    }
  213.  
  214.       /*Set these variables to their default value*/
  215.    *countDirs=TRUE;
  216.    *countFiles=FALSE;
  217.    strcpy(dirName,"");
  218.  
  219.    for(i=1;i<argc;i++)
  220.    {
  221.       if(argv[i][0]=='-')
  222.      switch(argv[i][1])
  223.      {
  224.         case 's':   /*Don't print the size of each directory*/
  225.         case 'S':
  226.            *countDirs=FALSE;
  227.            break;
  228.         case 'a':   /*Print the size of each directory*/
  229.         case 'A':
  230.            *countFiles=TRUE;
  231.            break;
  232.      }
  233.       else  /*If the first character wasn't '-', the argument must be the*/
  234.      strcpy(dirName,argv[i]);   /*directory name*/
  235.    }
  236.       /*If the user specified that directory sizes wouldn't be printed,*/
  237.       /*don't print out the file sizes either*/
  238.    if(*countDirs==FALSE)
  239.       *countFiles=FALSE;
  240.    return;
  241. }
  242.  
  243. /*Make the directory/file name, then print out the size*/
  244. void printSize(char *dirName,ULONG size)
  245. {
  246.    char sizeStr[16];
  247.  
  248.       /*Conver the size (int) to a string*/
  249.    stci_d(sizeStr,size);
  250.  
  251.       /*Print it out*/
  252.    fputs(sizeStr,stdout);
  253.  
  254.       /*Print out a TAB*/
  255.    fputs("\t",stdout);
  256.  
  257.       /*Print out the directory name, or '.' if it's the current directory*/
  258.    if(dirName[0]==NULL)
  259.       puts(".");
  260.    else
  261.       puts(dirName);
  262.  
  263.       /*Flush the output stream*/
  264.    flushall();
  265.    return;
  266. }
  267.  
  268. /*Print help*/
  269. void printHelp(void)
  270. {
  271.    puts("\nDave's DU V1.01 ©1991 by Dave Schreiber. All rights reserved.");
  272.    puts("\nUsage:");
  273.    puts(" du [-s][-a][<dir>]");
  274.    puts("-s -- Print only the grand total size");
  275.    puts("-a -- Print the size for each file");
  276.    puts("<dir> -- Starting directory");
  277.    puts("");
  278.    return;
  279. }
  280.  
  281. /*CTRL-C handler*/
  282. void ctrlC_Handler(void)
  283. {
  284.    signal(SIGINT,ctrlC_Handler);
  285.    quitNow=TRUE;
  286.    return;
  287. }
  288.  
  289.